#ifndef PROCESS_H
#define PROCESS_H

#include <boost/shared_ptr.hpp>
#include <list>

class Process;
typedef std::list< boost::shared_ptr<Process> > ProcessList;

//! This class represents a Process. 
//!
class Process
{
public:

	typedef boost::shared_ptr<Process> Ptr;

private:

	friend class ProcessManager;

protected:

	//! List of following processes dependent on finish.
	//! 
	ProcessList mDepOnFinish;

	//! List of following processes dependent on finish and success.
	//!
	ProcessList mDepOnSuccess;

	//! Whether the process is currently paused. A paused project receives no updates.
	//! A paused project can be resumed. Starts being false.
	bool mPaused;

	//! Whether the process has finished. A finished project receives no updates,
	//! it can't be restarted and in time it will be automatically removed 
	//! from the manager. Starts being false.
	bool mFinished;

	//! Whether the process has been successful. Set when the process finishes. Starts
	//! being false.
	bool mSuccessful;

	//! Whether the process has been initialized.
	//!
	bool mInitialized;

	//! Whether the process is currently attached to the manager.
	//!
	bool mAttached;

	//! An integer identifying the type of the process. 0 is the default generic type.
	//!
	int mType;

public:

	//! Constructs a new Process.
	//!
	Process(int type = 0);

	//! Destructs the Process.
	//!
	virtual ~Process();

	//! Returns true if the process is currently paused. 
	//!
	bool IsPaused() const;

	//! Pauses or resumes the process.
	//!
	//! @param pause true if the process should be paused, false otherwise.
	void Pause(bool pause);

	//! Returns true if the process has finished.
	//!
	bool IsFinished() const;

	//! Finishes the process. Is a no-op if the project is already finished.
	//!
	//! @param success Whether the process was successful or not. This may be
	//! overridden by the process' exit event.
	void Finish(bool success = true);

	//! Returns true if the process finished and was successful.
	//!
	bool IsSuccessful() const;

	//! Returns true if the process has been initialized. A process is initialized 
	//! just before its first OnUpdate.
	//!
	bool IsInitialized() const;

	//! Returns true if the process is currently active. That is, if OnUpdate is
	//! ready to be called by the manager.
	bool IsActive() const;

	//! Returns true if the process is currently attached to the manager.
	//!
	bool IsAttached() const;

	//! Returns the type of the process. The default type is 0.
	//!
	virtual int GetType() const;


	// EVENTS
	//

	//! Called when the process should update.
	//!
	virtual void OnUpdate(int delta) = 0;

	//! Called after the process finishes (and after setting error or success).
	//! May change success state.
	//!
	virtual void OnFinish();

	//! Called when the process is paused.
	//! @remark If the project is already paused, it is not called.
	//!
	virtual void OnPause();

	//! Called when the process is resumed, after being paused.
	//!
	virtual void OnResume();

	//! Called when the process is initialized, just before its first OnUpdate.
	//!
	virtual void OnInitialize();


	// DEPENDENT PROCESS
	//

	//! Adds a dependent process to the list of dependent processes.
	//!
	//! @param nextProc A smart pointer to the process to add.
	//! @param dependsOnSuccess If true, the process will only become active
	//! if the parent process has finished and was successful. Otherwise, it
	//! will become active whenever the parent has finished, regardless its success.
	void AddNext(Process::Ptr nextProc, bool dependsOnSuccess = false);

	//! Returns a reference to the specified next list.
	//!
	//! @param dependsOnSuccess If true, it will return the list of the dependent 
	//! processes that depend on Finished and Successful. 
	//! If false, it will return the list of the dependent processes that depend on
	//! Finished only.
	ProcessList const & GetNextList(bool dependsOnSuccess = false);

};


#endif